package com.classify.controller;

import com.classify.test.ClassifierFactory;
import com.classify.textClassify.ClassifyModel;
import com.classify.textClassify.Result;
import jxl.*;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;

@RestController
public class NewsController {
    static String seedsDir = null;
    static ClassifyModel cModel = null;


    @PostMapping("/oneNews")
    public Object newsOne(String content) {
        return classify(content);
    }

    @PostMapping("/oneMany")
    public Object newsMany(@RequestParam("file") MultipartFile file) {
        System.out.println(file.getName());
        List<Result> list = new ArrayList<>();

        File toFile = null;
        if(file.equals("")||file.getSize()<=0){
            file = null;
        }else {
            InputStream ins = null;
            try {
                ins = file.getInputStream();
                toFile = new File(file.getOriginalFilename());
                inputStreamToFile(ins, toFile);
                ins.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


        int i;
        Sheet sheet;
        Workbook book;
        Cell cell1, cell2;
        try {
            //hello.xls为要读取的excel文件名
            book= Workbook.getWorkbook(toFile);

            //获得第一个工作表对象(ecxel中sheet的编号从0开始,0,1,2,3,....)
            sheet=book.getSheet(0);
            //获取左上角的单元格
            //cell1=sheet.getCell(0,0);
            //System.out.println("标题："+cell1.getContents());

            i=1;
            while(true)
            {
                //获取每一行的单元格
                cell1=sheet.getCell(0,i);//（列，行）
                //内容
                cell2=sheet.getCell(1,i);
                if("".equals(cell1.getContents())==true)    //如果读取的数据为空
                    break;
                System.out.println("标题为" + cell2);
                list.add(classify(cell1.getContents()));
                i++;
            }
            book.close();
        }
        catch(Exception e)  { }
        return list;
        //return classify(content);
    }



    static{
        try {
            File file = ResourceUtils.getFile("classpath:seeds");
            seedsDir = file.getCanonicalPath();
        }catch (IOException e){
            e.printStackTrace();
        }

        double trainDataPercent = 0.5;
        //将元组中的第一个分支作为训练集
        Map<String, List<String>> trainSeeds = divideSeedsToTrainAndTest(seedsDir, trainDataPercent);
        //测试的数据
        //String content = "在今天晚上网络上传出了大量《Elden Ring》的泄露预告片段，而现在我们终于得见了一段相对完整的版本，一起来看看这段34秒版的《Elden Ring》预告。和之前VGC编辑形容的内容一样，本段预告中出现了口吐火焰的巨龙以及手持大剑的boss，此外我们也对骑马作战的场景有了匆匆一瞥。而根据Dusk Golem的消息，此次披露的预告其实是一年前制作的，其中展现的多数都是旧版场景。另外Dusk Golem表示本段片段来自于一段内部宣传片，实际上如果没有这次的泄露，这个宣传片“可能永远不会公开”。除此之外，Dusk Golem披露：《Elden Ring》开始是按照上世代游戏进行开发的，所以那些期待画面获得大幅提高的玩家可能会失望了，这款游戏的画面看起来很好，但没有到惊艳的地步。根据此前的爆料，在本月末我们就将能听到更多有关《Elden Ring》的相关消息，如果这些传闻属实，那么不久之后我们就能看到更加清晰完整的预告了（当然，可能在内容上和泄露的这段也会有不同）。有关《Elden Ring》开发进展的相关爆料，还请移步我们早先的报道查看。更多相关资讯请关注：Elden Ring专区<!--文章内容导航 开始--><!--文章内容导航 结束-->";
        //获取贝叶斯算法模块
        ClassifierFactory cf = new ClassifierFactory(seedsDir);
        cModel = cf.getClassifyModel("naiveBayes", "mm");

        //训练
        cModel.train(trainSeeds);
    }


    public static Result classify(String content){

        //分类
        Result result = testAccuracy(cModel, content);
        return result;
    }

    public static Result testAccuracy(ClassifyModel cModel, String content) {
        int all = 0;
        Result result = cModel.classify(content);
        System.out.println("共测试 " + all + " 篇文章");
        System.out.println("结果为：" + result.toString());
        return result;
    }

    //随机获取训练集
    public static Map<String, List<String>>  divideSeedsToTrainAndTest(String seedsDir, double trainDataPercent) {
        Map<String, List<String>> trainData = new HashMap<String, List<String>>();

        Random rand = new Random();

        File seeds = new File(seedsDir);
        //将当前的seeds中的分类集
        for(File tag : seeds.listFiles()) {
            //当前目录名
            String tagName = tag.getName();
            List<String> trainSeeds = new ArrayList<String>();
            for(File seed : tag.listFiles()) {
                //利用随机数将所有的文件分类为训练文件和测试文件
                if(rand.nextDouble() <= trainDataPercent) {
                    //训练集文件 绝对路径
                    trainSeeds.add(seed.getAbsolutePath());
                }
            }
            trainData.put(tagName, trainSeeds);
        }

        return trainData;
    }


    public static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
